/*
 * Copyright (C) 2012 lytsing.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.idreems.imagesns.ui;

import java.io.IOException;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.androidquery.AQuery;
import com.costum.android.widget.PullAndLoadListView;
import com.google.gson.Gson;
import com.idreems.AMapLocation.LocationManager;
import com.idreems.imagesns.Consts;
import com.idreems.imagesns.R;
import com.idreems.imagesns.adapters.StatusItemAdapter;
import com.idreems.imagesns.model.Statuses;
import com.idreems.imagesns.model.WeiboObject;
import com.idreems.imagesns.util.Preferences;
import com.idreems.imagesns.util.Util;
import com.jacp.menu.view.MenuView;
import com.jacp.menu.view.MenuView.OnMenuItemClickListener;
import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.Action;
import com.markupartist.android.widget.ActionBar.IntentAction;
import com.weibo.sdk.android.WeiboException;
import com.weibo.sdk.android.api.PlaceAPI;
import com.weibo.sdk.android.api.WeiboAPI.SORT3;
import com.weibo.sdk.android.net.RequestListener;

public class TimelineActivity extends BaseActivity
{

	private static final String TAG = "TimelineActivity";
	private static final int FIRST_PAGE = 1;
	private static final int DEFAULT_DISTANCE = 1000;

	private StatusItemAdapter mAdapter = null;
	private PullAndLoadListView mListView = null;

	private ActionBar mActionBar;
	private AQuery aq;

	private int mCurrentPage = FIRST_PAGE;
	private int mCurrentDistance = DEFAULT_DISTANCE;
	private long mLatesttime = 0;
	private AMapLocationListener mLocationRefreshListener;
	private AMapLocationListener mLocationLoadMoreListener;

	private final int[] mImgRes = { R.drawable.btn_insert_location_nor, R.drawable.cancel };
	private final Class<?>[] itemActivities = { LocationWeiboActivity.class, FriendTimelineActivity.class };
	private MenuView mMenuView;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		if (hasAccessToken())
		{
			initView();
		}
		else
		{
			Intent intent = new Intent(this, AuthenticatedActivity.class);
			startActivity(intent);
		}
	}

	private boolean hasAccessToken()
	{
		SharedPreferences prefs = Preferences.get(this);
		String token = prefs.getString(Preferences.ACCESS_TOKEN, null);
		String expires_in = String.valueOf(prefs.getLong(Preferences.EXPIRES_IN, 0));

		return (token != null && expires_in != null);
	}

	private Intent createComposeIntent()
	{
		Intent intent = new Intent(this, ComposeActivity.class);
		return intent;
	}

	public static Intent createIntent(Context context)
	{
		Intent intent = new Intent(context, TimelineActivity.class);
		return intent;
	}

	private void initView()
	{
		setContentView(R.layout.timeline);

		aq = new AQuery(this);

		mActionBar = (ActionBar) findViewById(R.id.actionbar);
		mActionBar.setHomeAction(new IntentAction(this, createIntent(this), R.drawable.logo_h));

		final Action composeAction = new IntentAction(this, createComposeIntent(), R.drawable.ic_action_compose);
		mActionBar.addAction(composeAction);

		mActionBar.addAction(new Action()
		{
			@Override
			public void performAction(View view)
			{
				nearbyStatus(FIRST_PAGE, getCurrentDistance());
			}

			@Override
			public int getDrawable()
			{
				return R.drawable.ic_action_refresh;
			}
		});

		mActionBar.addAction(new Action()
		{
			@Override
			public void performAction(View view)
			{
				showMenu();
			}

			@Override
			public int getDrawable()
			{
				return R.drawable.ic_action_share;
			}
		});

		mListView = ((PullAndLoadListView) findViewById(R.id.msg_list_item));

		// Set a listener to be invoked when the list should be refreshed.
		mListView.setOnRefreshListener(new PullAndLoadListView.OnRefreshListener()
		{
			@Override
			public void onRefresh()
			{
				nearbyStatus(FIRST_PAGE, getCurrentDistance());
			}
		});

		mListView.setOnLoadMoreListener(new PullAndLoadListView.OnLoadMoreListener()
		{

			public void onLoadMore()
			{
				loadMoreData(getCurrentPage() + 1, getCurrentDistance());
			}
		});

		mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));

		mAdapter = new StatusItemAdapter(this);

		nearbyStatus(FIRST_PAGE, getCurrentDistance());

		mListView.setOnItemClickListener(new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id)
			{

				// see: How to determine onItemClick for pulltorefreshlistview
				// http://stackoverflow.com/questions/10959030/how-to-determine-onitemclick-for-pulltorefreshlistview
				Statuses status = (Statuses) mListView.getItemAtPosition(position);

				if (status == null)
				{
					return;
				}
				else
				{
					Bundle bundle = new Bundle();
					bundle.putSerializable(Consts.STATUSES_KEY, status);

					Intent intent = new Intent(TimelineActivity.this, StatusDetailActivity.class);
					intent.putExtras(bundle);
					startActivity(intent);
				}
			}
		});
	}

	private void showLoadingIndicator()
	{
		aq.id(R.id.placeholder_loading).visible();
	}

	private void hideLoadingIndicator()
	{
		aq.id(R.id.placeholder_loading).gone();
	}

	private void showErrorIndicator()
	{
		aq.id(R.id.placeholder_error).visible();
	}

	private void hideErrorIndicator()
	{
		aq.id(R.id.placeholder_error).gone();
	}

	private String getLastSyncTime(String pre)
	{
		SharedPreferences prefs = Preferences.get(this);
		String time = prefs.getString(pre, "");
		return time;
	}

	private void setLastSyncTime(String time)
	{
		SharedPreferences.Editor editor = Preferences.get(this).edit();
		editor.putString(Preferences.PREF_LAST_SYNC_TIME, time);
		editor.commit();
	}

	private void showContents()
	{
		aq.id(R.id.timelist_list).visible();

		// FIXME: put it here, else will pop up "Tap to Refresh"
		mListView.setAdapter(mAdapter);
	}

	private void setLatestTime(long time)
	{
		android.util.Log.d(TAG, "setLatestTime: " + time);
		mLatesttime = time;
	}

	private long getLatestTime()
	{
		android.util.Log.d(TAG, "getLatestTime: " + mLatesttime);
		return mLatesttime;
	}

	private long getEndTime()
	{
		long r = mLatesttime != 0 ? System.currentTimeMillis() : 0;
		android.util.Log.d(TAG, "getEndTime: " + r);
		return r;
	}

	private void nearbyPhotosRefresh(final float lat, final float lon, final int page, int distance)
	{
		android.util.Log.d(TAG, "page: " + page);
		PlaceAPI statusAPI = new PlaceAPI(mAccessToken);
		statusAPI.nearbyPhotos(String.valueOf(lat), String.valueOf(lon), distance, getLatestTime(), getEndTime(), SORT3.SORT_BY_TIME, 50, page, false, new RequestListener()
		{
			@Override
			public void onComplete(String result)
			{
				WeiboObject response = null;
				try
				{
					Gson gson = new Gson();
					response = gson.fromJson(result, WeiboObject.class);
				}
				catch (Exception e)
				{
				}
				if (response == null || response != null && response.statuses == null)
				{
					runOnUiThread(new Runnable()
					{

						@Override
						public void run()
						{
							Util.showToast(TimelineActivity.this, getString(R.string.no_new_blog_toast));
							hideLoadingIndicator();

							setLastSyncTime(Util.getNowLocaleTime());
							// Call onRefreshComplete when the list has been refreshed.
							mListView.onRefreshComplete();
							mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));
						}
					});
					return;
				}
				if (response != null && response.statuses != null)
				{

					// update latest time
					if (getCurrentPage() == FIRST_PAGE)
					{
						try
						{
							setLatestTime(Util.parseDate(response.statuses.get(0).created_at).getTime());
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}

					android.util.Log.d(TAG, String.format("+%d/%d", response.statuses.size(), response.total_number));
				}
				mAdapter.addNewestStatuses(response.statuses);
				final int count = response.statuses.size();
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						hideLoadingIndicator();
						aq.id(R.id.placeholder_error).gone();

						showContents();
						setLastSyncTime(Util.getNowLocaleTime());
						// Call onRefreshComplete when the list has been refreshed.
						mListView.onRefreshComplete();
						mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));

						mAdapter.notifyDataSetChanged();
						Util.showToast(TimelineActivity.this, String.format(getString(R.string.new_blog_toast), count));
					}
				});
			}

			@Override
			public void onError(final WeiboException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						showErrorIndicator();
						aq.id(R.id.error_msg).text(e.getMessage());
						aq.id(R.id.retry_button).clicked(new OnClickListener()
						{

							@Override
							public void onClick(View v)
							{
								nearbyStatus(getCurrentPage(), getCurrentDistance());
							}
						});
					}
				});
			}

			@Override
			public void onIOException(final IOException e)
			{
			}

		});
	}

	private void nearbyPhotosLoadMore(final float lat, final float lon, final int page, int distance)
	{
		android.util.Log.d(TAG, "page: " + page);
		PlaceAPI statusAPI = new PlaceAPI(mAccessToken);
		statusAPI.nearbyPhotos(String.valueOf(lat), String.valueOf(lon), distance, 0, 0, SORT3.SORT_BY_TIME, 50, page, false, new RequestListener()
		{
			@Override
			public void onComplete(String result)
			{
				WeiboObject response = null;
				try
				{
					Gson gson = new Gson();
					response = gson.fromJson(result, WeiboObject.class);
				}
				catch (Exception e)
				{
				}
				if (response == null || response != null && response.statuses == null)
				{
					runOnUiThread(new Runnable()
					{

						@Override
						public void run()
						{
							Util.showToast(TimelineActivity.this, getString(R.string.no_old_blog_toast));
							hideLoadingIndicator();

							mListView.onLoadMoreComplete();
						}
					});
					return;
				}
				if (response != null && response.statuses != null)
				{
					android.util.Log.d(TAG, String.format("+%d/%d", response.statuses.size(), response.total_number));
				}

				mAdapter.addStatuses(response.statuses);
				final int count = response.statuses.size();
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						hideLoadingIndicator();
						aq.id(R.id.placeholder_error).gone();

						mAdapter.notifyDataSetChanged();
						mListView.onLoadMoreComplete();

						Util.showToast(TimelineActivity.this, String.format(getString(R.string.old_blog_toast), count));
					}
				});
			}

			@Override
			public void onError(final WeiboException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						displayToast("Error:" + e.getMessage());
						// Notify the loading more operation has finished
						// TODO: remove the OnLoadMoreListener of the listview as
						// there has error or no more items to load.
						mListView.onLoadMoreComplete();
					}
				});
			}

			@Override
			public void onIOException(final IOException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						displayToast("Error:" + e.getMessage());
						mListView.onLoadMoreComplete();
					}
				});
			}

		});
	}

	@Override
	public void onDestroy()
	{
		LocationManager.sharedInstance().destroy();
		super.onDestroy();
	}

	protected void onPause()
	{
		LocationManager.sharedInstance().stopLocatingMyLocation();
		super.onPause();
	}

	private void setCurrentPage(int page)
	{
		mCurrentPage = page;
	}

	private int getCurrentPage()
	{
		return mCurrentPage;
	}

	private void setCurrentDistance(int distance)
	{
		mCurrentDistance = distance;
	}

	private int getCurrentDistance()
	{
		return mCurrentDistance;
	}

	public void loadMoreData(final int page, final int distance)
	{
		hideErrorIndicator();
		showLoadingIndicator();

		setCurrentPage(page);
		setCurrentDistance(distance);

		if (LocationManager.sharedInstance().getLocation() != null)
		{
			nearbyPhotosLoadMore(Consts.COORDINATES_LAT, Consts.COORDINATES_LONG, page, distance);
		}
		else
		{
			mLocationLoadMoreListener = new AMapLocationListener()
			{
				@Override
				public void onStatusChanged(String provider, int status, Bundle extras)
				{
				}

				@Override
				public void onProviderEnabled(String provider)
				{
				}

				@Override
				public void onProviderDisabled(String provider)
				{
				}

				@Override
				public void onLocationChanged(Location location)
				{
				}

				@Override
				public void onLocationChanged(AMapLocation location)
				{
					LocationManager.sharedInstance().removeUpdates(mLocationLoadMoreListener);
					mLocationLoadMoreListener = null;

					final AMapLocation loc = location;
					if (loc != null)
					{
						runOnUiThread(new Runnable()
						{
							@Override
							public void run()
							{
								nearbyPhotosLoadMore((float) loc.getLatitude(), (float) loc.getLongitude(), page, distance);
							}
						});
					}
				}
			};
			LocationManager.sharedInstance().requestLocationUpdates(this, mLocationLoadMoreListener);
		}
	}

	public void nearbyStatus(final int page, final int distance)
	{
		hideErrorIndicator();
		showLoadingIndicator();

		setCurrentPage(page);
		setCurrentDistance(distance);

		if (LocationManager.sharedInstance().getLocation() != null)
		{
			nearbyPhotosRefresh(Consts.COORDINATES_LAT, Consts.COORDINATES_LONG, page, distance);
		}
		else
		{
			mLocationRefreshListener = new AMapLocationListener()
			{

				@Override
				public void onStatusChanged(String provider, int status, Bundle extras)
				{
				}

				@Override
				public void onProviderEnabled(String provider)
				{
				}

				@Override
				public void onProviderDisabled(String provider)
				{
				}

				@Override
				public void onLocationChanged(Location location)
				{
				}

				@Override
				public void onLocationChanged(AMapLocation location)
				{
					LocationManager.sharedInstance().removeUpdates(mLocationRefreshListener);
					mLocationRefreshListener = null;

					final AMapLocation loc = location;
					if (loc != null)
					{
						Double geoLat = location.getLatitude();
						Double geoLng = location.getLongitude();
						String cityCode = "";
						String desc = "";
						Bundle locBundle = location.getExtras();
						if (locBundle != null)
						{
							cityCode = locBundle.getString("citycode");
							desc = locBundle.getString("desc");
						}
						String str = ("定位成功:(" + geoLng + "," + geoLat + ")" + "\n精    度    :" + location.getAccuracy() + "米" + "\n城市编码:" + cityCode + "\n位置描述:" + desc);
						Log.d(TAG, str);

						runOnUiThread(new Runnable()
						{
							@Override
							public void run()
							{
								nearbyPhotosRefresh((float) loc.getLatitude(), (float) loc.getLongitude(), page, distance);
							}
						});
					}
				}
			};
			LocationManager.sharedInstance().requestLocationUpdates(this, mLocationRefreshListener);
		}
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		// TODO Auto-generated method stub
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
		{
			Exit();
		}

		return super.onKeyDown(keyCode, event);
	}

	void Exit()
	{
		Builder bExit = new AlertDialog.Builder(this);
		bExit.setTitle(R.string.exist_tip_title);
		bExit.setMessage(R.string.exist_tip_message);
		bExit.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
		{

			@Override
			public void onClick(DialogInterface dialog, int which)
			{
				// TODO Auto-generated method stub
				dialog.dismiss();
				TimelineActivity.this.finish();
			}
		});
		bExit.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
		{

			@Override
			public void onClick(DialogInterface dialog, int which)
			{
				dialog.dismiss();
			}
		});
		bExit.create().show();
	}

	private void showMenu()
	{
		if (null == mMenuView)
		{
			mMenuView = new MenuView(this);
			// mMenuView.setWidth(300);
			mMenuView.setImageRes(mImgRes);
			mMenuView.setAnimStyle(R.style.popup_in_out);
			mMenuView.setBackgroundResource(R.drawable.bg);
			mMenuView.setText(getResources().getStringArray(R.array.menu_text));
			mMenuView.setOnMenuItemClickListener(new OnMenuItemClickListener()
			{
				@Override
				public void onMenuItemClick(AdapterView<?> parent, View view, int position)
				{
					if (itemActivities != null && itemActivities.length > position)
					{
						Intent intent = new Intent(TimelineActivity.this, itemActivities[position]);
						startActivity(intent);
					}
				}

				@Override
				public void hideMenu()
				{
					mMenuView.dismiss();
					mMenuView = null;
				}

			});
		}
		mMenuView.show();
	}
}
